﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using XmlStudio.Helper;

namespace XmlStudio.Controls {
    /// <summary>
    /// Custom canvas class.
    /// </summary>
    public partial class DesignerCanvas : Canvas {
        #region Fields
        private Point? rubberbandSelectionStartPoint;
        #endregion

        #region Properties
        //private SelectionService selectionService;
        internal SelectionService SelectionService {
            get { return SelectionService.GetCurrentInstance(this); }
        }
        #endregion

        #region Event handlers
        /// <summary>
        /// Invoked on MouseDown event.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnMouseDown(MouseButtonEventArgs e) {
            base.OnMouseDown(e);
            if((e.Source == this || e.Source is Border) & e.ChangedButton == MouseButton.Left) {
                // in case that this click is the start of a 
                // drag operation we cache the start point
                this.rubberbandSelectionStartPoint = new Point?(e.GetPosition(this));

                // if you click directly on the canvas all 
                // selected items are 'de-selected'

                this.SelectionService.ClearSelection();
                //SelectionService.ClearSelection();
                Focus(); // causes scrollviewer to scroll if enabled
                e.Handled = true;
            }
        }

        /// <summary>
        /// Inovked on MouseMove event.
        /// </summary>
        /// <param name="e">The event data.</param>
        protected override void OnMouseMove(MouseEventArgs e) {
            base.OnMouseMove(e);

            // if mouse button is not pressed we have no drag operation, ...
            if(e.LeftButton != MouseButtonState.Pressed)
                this.rubberbandSelectionStartPoint = null;

            // ... but if mouse button is pressed and start
            // point value is set we do have one
            if(this.rubberbandSelectionStartPoint.HasValue) {
                // create rubberband adorner
                AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);
                if(adornerLayer != null) {
                    var adorner = new RubberbandAdorner(this, rubberbandSelectionStartPoint);
                    adornerLayer.Add(adorner);
                }
            }

            e.Handled = true;
        }

        /// <summary>
        /// Invoked on Measure event.
        /// </summary>
        /// <param name="constraint"></param>
        /// <returns></returns>
        protected override Size MeasureOverride(Size constraint) {
            var size = new Size();

            foreach(UIElement element in this.InternalChildren) {
                double left = GetLeft(element);
                double top = GetTop(element);
                left = double.IsNaN(left) ? 0 : left;
                top = double.IsNaN(top) ? 0 : top;

                //measure desired size for each child
                element.Measure(constraint);

                Size desiredSize = element.DesiredSize;
                if(!double.IsNaN(desiredSize.Width) && !double.IsNaN(desiredSize.Height)) {
                    size.Width = Math.Max(size.Width, left + desiredSize.Width);
                    size.Height = Math.Max(size.Height, top + desiredSize.Height);
                }
            }
            // add margin
            size.Width += 10;
            size.Height += 10;
            return size;
        }
        #endregion
    }
}